package com.xjoyt.pay.master.core.order.handle.callback;

import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.gateway.params.CallbackParam;
import com.xjoyt.pay.master.core.order.handle.AbstractOrderCallbackHandle;
import com.xjoyt.pay.master.dto.CallbackResult;
import com.xjoyt.pay.master.po.Company;
import com.xjoyt.pay.master.po.CompanyProfit;
import com.xjoyt.pay.master.po.CompanyRate;
import com.xjoyt.pay.master.po.DistributorProfit;
import com.xjoyt.pay.master.po.Order;
import com.xjoyt.pay.master.repository.CompanyProfitRepository;
import com.xjoyt.pay.master.repository.CompanyRateRepository;
import com.xjoyt.pay.master.repository.CompanyRepository;
import com.xjoyt.pay.master.repository.DistributorProfitRepository;

/**
 * 处理分润
 * 
 * @author Administrator
 *
 */
@Component
public class ProfitHandle extends AbstractOrderCallbackHandle {

	@Autowired
	private DistributorProfitRepository distributorProfitRepository;

	@Autowired
	private CompanyProfitRepository companyProfitRepository;

	@Autowired
	private CompanyRepository companyRepository;

	@Autowired
	private CompanyRateRepository companyRateRepository;

	@Override
	public ExecuteResult<CallbackResult> handle(CallbackParam param, Order entity) throws Exception {
		if (entity.merchant == null || entity.merchant.distributor == null
				|| entity.merchant.distributor.company == null || entity.orderConfig == null
				|| entity.orderConfig.channel == null) {
			throw new Exception("订单失效");
		}

		DistributorProfit profit = distributorProfitRepository.findOneByOrderIdAndDistributorId(entity.id,
				entity.merchant.distributor.id);
		if (profit == null) {
			profit = new DistributorProfit();
			profit.addedDate = new Date();
			profit.distributor = entity.merchant.distributor;
			profit.order = entity;
			profit.type = entity.payType;
			profit.rate = entity.rate;
			profit.money = entity.money;
			profit.limit = entity.limit;
			profit.poundage = entity.poundage;
			profit.minimum = entity.minimum;
			profit.costPoundage = entity.costPoundage;
			if (entity.costLimit > 0 && entity.money * entity.orderConfig.costRate >= entity.costLimit) {
				profit.costRate = 0D;
				profit.costLimit = entity.costLimit;
				profit.costMinimum = 0L;
			} else if (entity.costMinimum > 0
					&& entity.money * entity.orderConfig.costRate <= entity.costMinimum) {
				profit.costRate = 0D;
				profit.costMinimum = entity.costMinimum;
				profit.costLimit = 0L;
			} else {
				profit.costRate = entity.orderConfig.costRate;
				profit.costMinimum = 0L;
				profit.costLimit = 0L;
			}
			distributorProfitRepository.save(profit);
		}

		CallbackResult result = new CallbackResult();
		result.merchantId = entity.merchant.id;
		result.distributorId = entity.merchant.distributor.id;
		result.companyId = entity.merchant.distributor.company.id;

		setProfit(entity.merchant.distributor.company, profit.costRate, profit.costLimit, profit.costPoundage,
				profit.costMinimum, entity);
		return getNext().handle(param, entity);
	}

	/**
	 * 设置机构分润
	 * 
	 * @param company
	 * @param rate
	 * @param order
	 */
	private void setProfit(Company company, double rate, long limit, long poundage, long minimum, Order order) {
		if (StringUtils.isBlank(company.parentId)) {
			CompanyProfit profit = companyProfitRepository.findOneByOrderIdAndCompanyId(order.id, company.id);
			if (profit == null) {
				profit = new CompanyProfit();
				profit.addedDate = new Date();
				profit.company = company;
				profit.order = order;
				profit.type = order.payType;
				profit.rate = rate;
				profit.money = order.money;
				profit.limit = limit;
				profit.poundage = poundage;
				profit.minimum = minimum;
				profit.costPoundage = order.channelPoundage;
				if (order.channelLimit > 0 && order.money * order.channelRate >= order.channelLimit) {
					profit.costRate = 0D;
					profit.costLimit = order.channelLimit;
					profit.costMinimum = 0L;
				} else if (order.channelMinimum > 0
						&& order.money * order.channelRate <= order.channelMinimum) {
					profit.costRate = 0D;
					profit.costMinimum = order.channelMinimum;
					profit.costLimit = 0L;
				} else {
					profit.costRate = order.channelRate;
					profit.costMinimum = 0L;
					profit.costLimit = 0L;
				}
			}
			companyProfitRepository.save(profit);
			return;
		}

		CompanyRate companyRate = companyRateRepository.findOneByCompanyIdAndType(company.id, order.payType);
		if (companyRate == null)
			return;

		double costRate = companyRate.rate;
		CompanyProfit profit = companyProfitRepository.findOneByOrderIdAndCompanyId(order.id, company.id);
		if (profit == null) {
			profit = new CompanyProfit();
			profit.addedDate = new Date();
			profit.company = company;
			profit.order = order;
			profit.type = order.payType;
			profit.rate = rate;
			profit.costRate = costRate;
			profit.money = order.money;
			companyProfitRepository.save(profit);
		}
		Company parent = companyRepository.findOne(company.parentId);
		if (parent != null)
			setProfit(parent, costRate, limit, poundage, minimum, order);
	}
}
